package com.bjsxt.service.impl;

import com.baomidou.mybatisplus.extension.enums.ApiErrorCode;
import com.baomidou.mybatisplus.extension.exceptions.ApiException;
import com.bjsxt.config.geetest.GeetestLib;
import com.bjsxt.dto.LoginFormDto;
import com.bjsxt.feign.JwtToken;
import com.bjsxt.feign.OAuth2FeignClient;
import com.bjsxt.model.LoginUserResultVo;
import com.bjsxt.service.LoginService;
import com.bjsxt.util.GeetestUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * description:
 * 会员登录业务业务层接口实现类
 *
 * @author ALIENWARE <br />
 * @date 2021/9/6
 */
@Service
@Slf4j
public class LoginServiceImpl implements LoginService {

    /**
     * authorization-server openFegin 远程调用服务接口
     */
    @Autowired
    private OAuth2FeignClient oAuth2FeignClient;

    /**
     * 就是 Auth2 授权生产的第三方加密的值 账户: coin-api 密码: coin-secret 生成的加密值
     */
    @Value("${basic.token:Basic Y29pbi1hcGk6Y29pbi1zZWNyZXQ=}")
    private String basicToken;

    /**
     * Redis 客户端操作对象
     */
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    /**
     * 极验验证核心类
     */
    @Autowired
    private GeetestLib geetestLib;

    /**
     * 会员的登录
     *
     * @param loginFormDto 会员登录数据传输对象
     * @return 登录成功的 token 数据对象的值
     */
    @Override
    public LoginUserResultVo login(LoginFormDto loginFormDto) {
        // log.info("用户{}开始登录",loginFormDto.getUsername());
        // 检查登录数据对象的合法性
        GeetestUtil.checkFormData(loginFormDto, geetestLib, redisTemplate);
        // 获取 token 需要远程调用 authorization-server 服务进行 token 的获取
        ResponseEntity<JwtToken> tokenResponseEntity = oAuth2FeignClient.getToken("password", loginFormDto.getUsername(), loginFormDto.getPassword(), "member_type", basicToken);
        // 如果获取的数据没有成功抛出异常
        if (tokenResponseEntity.getStatusCode() != HttpStatus.OK)
            throw new ApiException(ApiErrorCode.FAILED);
        // 正常取出返回的对象
        JwtToken jwtToken = tokenResponseEntity.getBody();
        // 取出我们的 token 值
        String token = jwtToken.getAccessToken();
        // log.info("远程调用授权服务器成功,获取的 token 为{}", JSON.toJSONString(jwtToken, true));
        // 创建登录成功的返回值对象
        LoginUserResultVo loginUserResultVo = new LoginUserResultVo(loginFormDto.getUsername(), jwtToken.getExpiresIn(), jwtToken.getTokenType() + ' ' + token, jwtToken.getRefreshToken());
        // 将 token 数据存储在 redis 里面, 否则网关验证的时候是进入不到对应的服务的
        redisTemplate.opsForValue().set(token, "", jwtToken.getExpiresIn(), TimeUnit.SECONDS);
        // 返回登录成功的 token 数据对象
        return loginUserResultVo;
    }
}
